#include "backup_client.h"
#include "fileUtil.hpp"

cloudBackup::Backup_Client::Backup_Client(QObject *parent, const std::string &backupDir, int usrID)
    : QObject(parent)
    , _backupDir(backupDir)
    , _dirWatcher(new DirectoryWatcher(QString::fromStdString(_backupDir)))
    , _usrID(usrID)
{
    _dataManager = new DataManager(_usrID);

    // 连接信号到对应的槽
    connect(_dirWatcher, &DirectoryWatcher::fileAdded, this, &cloudBackup::Backup_Client::fileADD);
    connect(_dirWatcher, &DirectoryWatcher::fileModified, this, &cloudBackup::Backup_Client::fileMODIFY);
    connect(_dirWatcher, &DirectoryWatcher::fileRemoved, this, &cloudBackup::Backup_Client::fileREMOVE);
}

std::string cloudBackup::Backup_Client::GetFileSelfEtag(const std::string &filePath)
{
    // usrID-a.txt-fsize-ctime
    FileUtil fileUtil(filePath);
    std::stringstream ss;
    ss << std::to_string(_usrID) << "-" <<fileUtil.FileName() << "-" << fileUtil.FileSize() << "-" << fileUtil.LastCTime();
    return ss.str();
}

bool cloudBackup::Backup_Client::Upload(const std::string &filename)
{
    // 1. 获取文件数据
    FileUtil fileUtil(filename);
    std::string content;
    fileUtil.GetContent(&content);

    // 2. 搭建http客户端上传文件
    httplib::Client client(SERVER_ADDR, SERVER_PORT);

    httplib::MultipartFormData item;
    item.name = "file";

    // item.filename = FileUtil::UrlEncode(fileUtil.FileName());
    item.filename = fileUtil.FileName();
    item.content = content;
    item.content_type = "application/octet-stream";

    httplib::MultipartFormDataItems items;
    items.push_back(item);

    // std::string uploadReq = "/upload/" + std::to_string(_usrID) + "/" + FileUtil::UrlEncode(GetFileSelfEtag(filename));
    std::string uploadReq = "/upload/" + std::to_string(_usrID) + "/" + GetFileSelfEtag(filename);

    qDebug() << "uploadReq" << QString::fromStdString(uploadReq);

    auto httpResult = client.Post(uploadReq, items);
    if (!httpResult || httpResult->status != 200)
    {
        qDebug() << "httpResult->status: " << httpResult->status;
        return false;
    }
    return true;
}

void cloudBackup::Backup_Client::fileADD(const QString &filePath)
{
    std::string std_filePath = filePath.toStdString();
    //qDebug() << "fileADD(): " << filePath;

    qDebug() << filePath << "need upload!";
    // 需要上传 上传后需要插入到数据库
    _dataManager->Insert_Table(std_filePath, GetFileSelfEtag(std_filePath));
    if (Upload(std_filePath) == true) // 上传成功 代表该文件已备份 需要添加备份信息
    {
        qDebug() << filePath << "upload success!";
        //_dataManager->Insert_Table(std_filePath, GetFileSelfEtag(std_filePath));
    }
}

void cloudBackup::Backup_Client::fileMODIFY(const QString &filePath)
{
    // 此时的文件被修改经过上层处理已经是 被修改且3s内未修改的"修改"
    // qDebug() << "cloudBackup::Backup_Client::fileMODIFY" << filePath;
    std::string std_filePath = filePath.toStdString();
    qDebug() << filePath << "need upload!";
    // 需要上传 上传后修改数据库对应字段
    _dataManager->Modify_Table(std_filePath, GetFileSelfEtag(std_filePath), _usrID);
    if (Upload(std_filePath) == true) // 上传成功 代表该文件已备份 需要更新备份信息
    {
        qDebug() << filePath << "upload success!";
        // 文件被修改 更新数据库记录file_etag file_status
        //_dataManager->Modify_Table(std_filePath, GetFileSelfEtag(std_filePath), _usrID);
    }
}

void cloudBackup::Backup_Client::fileREMOVE(const QString &filePath)
{
    qDebug() << filePath << "need upload!";
    std::string std_filePath = filePath.toStdString();
    // 文件被删除 根据file_etag删除数据库记录 错误！文件已被删除无法计算空文件的etag
    // 应该根据用户名和路径唯一标识一条记录 继而删除该记录
    _dataManager->Remove_Table(_usrID, filePath.toStdString());
}


